﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microhard.Core.DBUtility;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

namespace Microhard.Core.Algorithm
{
    public class AlgCompare
    {
        public static byte[] SeriesDataToByte(object model)
        {
            byte[] rtn = null;
            Type type = model.GetType();
            using (var ms = new MemoryStream())
            {
                BinaryFormatter bf = new BinaryFormatter();
                bf.Serialize(ms, model);
                rtn = ms.ToArray();
            }
            return rtn;
        }

        public static object DeseriesBytesToObject(byte[] data)
        {
            object rtn = null;
            using (var ms = new MemoryStream(data))
            {
                BinaryFormatter bf = new BinaryFormatter();
                rtn = bf.Deserialize(ms);
            }
            return rtn;
        }

        public static void SetPKIDPropertyValue(ref object e, object value)
        {
            Type t = e.GetType();
            //获得带有ModelPKIDAttribute属性的字段
            foreach (var p in t.GetProperties())
            {
                Guid pkid = Guid.Empty;
                var atrs = p.GetCustomAttributes(false);
                if (atrs != null)
                {
                    foreach (var a in atrs)
                    {
                        if (a is ModelPKIDAttribute)
                        {
                            var pkidValue = Guid.Parse(p.GetValue(e, null).ToString());
                            if (pkidValue == Guid.Empty)
                            {
                                p.SetValue(e, value, null);
                                break;
                            }
                        }
                    }
                }
            }
        }

        public static void SetPKIDPropertyValue<T>(ref T e, object value)
        {
            Type t = e.GetType();
            //获得带有ModelPKIDAttribute属性的字段
            foreach (var p in t.GetProperties())
            {
                Guid pkid = Guid.Empty;
                var atrs = p.GetCustomAttributes(false);
                if (atrs != null)
                {
                    foreach (var a in atrs)
                    {
                        if (a is ModelPKIDAttribute)
                        {
                            var pkidValue = Guid.Parse(p.GetValue(e, null).ToString());
                            if (pkidValue == Guid.Empty)
                            {
                                p.SetValue(e, value, null);
                                break;
                            }
                        }
                    }
                }
            }
        }

        public static string GetValue(object e, string fieldName)
        {
            string rtn = string.Empty;
            if (e == null)
                return rtn;

            Type t = e.GetType();
            //TODO使用GetProperties可以获得基类的PKID,这样对于继承类型会出现错误
            foreach (var p in t.GetProperties())
            {
                if (p.Name == fieldName)
                {
                    rtn = p.GetValue(e, null).ToString();
                }

            }
            return rtn;
        }

        public static List<DicValueTypeModel> GetDicTxtNameWithDicFieldValue(object e)
        {
            List<DicValueTypeModel> rtn = new List<DicValueTypeModel>();
            if (e == null)
                return rtn;

            Type t = e.GetType();
            //TODO使用GetProperties可以获得基类的PKID,这样对于继承类型会出现错误
            foreach (var p in t.GetProperties())
            {
                var atrs = p.GetCustomAttributes(false);
                foreach (var a in atrs)
                {
                    if (a is ModelReadTxtFromoCache)
                    {
                        var mrtc = a as ModelReadTxtFromoCache;
                        var dicField = t.GetProperty(mrtc.IDFieldName);
                        var id = dicField.GetValue(e, null);
                        if (id != null)
                        {
                            rtn.Add(new DicValueTypeModel
                            {
                                FieldName = p.Name,
                                Value = id.ToString(),
                                PCDType = mrtc.PCDName,
                                UsingType = mrtc.UsingType,
                                WFInstanceFieldName = mrtc.WFInstanceFieldName
                            });
                        }
                    }
                }
            }
            return rtn;
        }

        public static Guid GetPKID<T>(object e)
        {
            if (e == null)
                return Guid.Empty;
            Guid rtn = Guid.Empty;
            Type t = e.GetType();
            //获得带有ModelPKIDAttribute属性的字段
            //TODO使用GetProperties可以获得基类的PKID,这样对于继承类型会出现错误
            foreach (var p in t.GetProperties())
            {
                Guid pkid = Guid.Empty;
                var atrs = p.GetCustomAttributes(false);
                if (atrs != null)
                {
                    foreach (var a in atrs)
                    {
                        if (a is T)
                        {
                            rtn = Guid.Parse(p.GetValue(e, null).ToString());
                            break;
                        }
                    }
                }
                if (rtn != Guid.Empty)
                    break;
            }
            return rtn;
        }

        /// <summary>
        /// 比较，获得哪些数据是需要添加，哪些数据需要删除
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="existData"></param>
        /// <param name="newData"></param>
        /// <param name="comparer"></param>
        /// <param name="toDelete"></param>
        /// <param name="toAdd"></param> 
        public static void DataCompareForCreateAndDelete<T>(List<T> existData, List<T> newData, IComparer<T> comparer, out List<T> toDelete, out List<T> toAdd)
        {
            //TODO IComparer 与 ICompareable 有什么区别?
            toDelete = new List<T>();
            toAdd = new List<T>();
            //识别需要删除的数据
            if ((newData == null || newData.Count == 0) && (existData != null || existData.Count() > 0))
            {
                toDelete.AddRange(existData);
            }
            else
            {
                foreach (var ext in existData)
                {
                    bool willDelteRole = true;
                    foreach (var ne in newData)
                    {

                        if (comparer.Compare(ext, ne) == 0)
                        {
                            willDelteRole = false;
                            break;
                        }
                    }
                    if (willDelteRole)
                    {
                        toDelete.Add(ext);
                    }
                }

                //识别需要增加的Data
                foreach (var ne in newData)
                {
                    bool willAddRole = true;
                    foreach (var ext in existData)
                    {
                        if (comparer.Compare(ext, ne) == 0)
                        {
                            willAddRole = false;
                            break;
                        }
                    }
                    if (willAddRole)
                    {
                        toAdd.Add(ne);
                    }
                }
            }
        }
    }
}
